/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package MemoriaIntermedia;

import java.util.LinkedList;
import java.util.Queue;
import java.util.logging.Logger;


/**
 *
 * @author UNSAAC73
 */
public class GestorMemoriaIntermedia {
    
    /*
     * representa sus abstracciones de unn gestor de memoria intermedia
     */
    
    static final Logger logger = Logger.getLogger("gestion de buffer");
    /*
     * representa a los bloques de la memoria intermesdia a bufer 0
     */
    private Pagina[] Buffer;
    /*numero de paginas que esta en toral en el buffer*/
    private int numeroPagina;
    /*posicion en el buffer de la ultima pagina colocada*/
    private int PosicionUltimaPagina = -1 ; /*se inicaliza en -1 porque al inicio no habra nada
     * cola para el control de sustitucion basada en el LRU
          */
    private Queue colaLRU;

    public GestorMemoriaIntermedia(int numeroPagina) {
        this.numeroPagina = numeroPagina;
        //creamos el buffer con paginas vacias 
        Buffer = new Pagina[numeroPagina];
        //crear una cola fifo
        colaLRU = new LinkedList<Integer>();
        
    }
    /*devuelve una pagina conociendo el numero de paginas
     * @param numero de pagina es el id de la pagina que queremos devolver
     * @return ña pagina del id de  pagina proporcionada
     */
    public Pagina recuperarPaginaDelBuffer(int numeroPagina){
        //verificamos si la pagina esra en el buffer
        int posicion = posicionDePaginaEnBuffer(numeroPagina);
        //si encuentra la pagina devera actualizar el lru 
        if(posicion>=0) //verificamos si la pagina sta en eel buffer
        {
            //marcar pagina o bloque como recientemente usado
            colaLRU.remove(numeroPagina);
            colaLRU.add(numeroPagina);
            //devolver la pagina del buffer al solicitante
            return Buffer[posicion];
              
        }
        //caso contrario solo nos mostrara nulo(es decri que 
        return null;
    }
    /*
     * poner una pagina en el buffer de la memori aintermedi
     * @param pagina .- es la pagina a ser inserada en el buffrer
     * @return es la pagina que sera descartada si el buffer esta opcupado 
     */
    public Pagina ponerPaginaEnBuffer(Pagina pagina)
    {
        //si la pagina esta en el buffer
        if(estaPaginaEnBuffer(pagina))
        {
            //no descartara ninguna pagina o bloque
            return null;
        }//si la pagina no esta en el buffer pero hay epacionen le buffer
        else if(!bufferLleno()){
            //averiguar la nueva pagina si hay bloque o pagina libre
            PosicionUltimaPagina++;
            Buffer[PosicionUltimaPagina]=pagina;
            //actualizar el lru
            colaLRU.remove(PosicionUltimaPagina);
            colaLRU.add(PosicionUltimaPagina);
            return null;
            
        }
        else{
            //recuperar lapagina a descartar
            //identificaar el id de pagina a descartar de la cola lru
            int numeroPaginaDescartada = (Integer) colaLRU.remove();
            //conociendo elid de la pagina ubicar la,posicion de la pagina em eñ buffer
            int posicion =posicionDePaginaEnBuffer(numeroPaginaDescartada);
            //extraer la pagina a descartar del buffer
            Pagina paginaDescartada =  Buffer[posicion];
            //acualiza la nueva pagina en la posicion de la pagina descartada
            Buffer[posicion] = pagina;
            //hacer que le id de la nueva pagian sea el m,as recientem,ente referencado
            colaLRU.add(pagina.getNumeroPagina());
            //fianlmente se retorna la pagina descartada
            return paginaDescartada;
        }
    }
    private  int posicionDePaginaEnBuffer(int numeroPagina){
        int posicion = -1;
        for(int i = 0; i< Buffer.length;i++){
            if((Buffer[1] != null) && (numeroPagina== Buffer[1].getNumeroPagina())){
                posicion=i;
                break;
            }
        }
        return posicion;
    }
    private boolean estaPaginaEnBuffer(Pagina pagina){
        return (posicionDePaginaEnBuffer(pagina.getNumeroPagina() )!= -1);
    }
    private boolean bufferLleno(){
        return numeroPagina-1 ==PosicionUltimaPagina;
    }
    @Override
    public String toString(){
        String resultado= "";
        for(int i = 0;i<Buffer.length;i++) {
            resultado +="Pagina[ "+i+"] : "+ Buffer[i]+"\n";
        }
        return resultado + "\n"+this.colaLRU;
    }
    public static void main (String[] args){
        //crear un gestor de memoria
        GestorMemoriaIntermedia gestorBuffer = new GestorMemoriaIntermedia(6);
        //paginas del disco
        System.out.println("Paginas del disco: ");
        Pagina[] paginas = new Pagina[10];
        for (int i = 0; i < paginas.length; i++) {
            Pagina pagina = new Pagina(i,"p"+i);
            paginas[i]= pagina;
            System.out.println(pagina);
            
        }
        System.out.println("contenido del gestor");
        System.out.println(gestorBuffer);
        for (int i = 0; i < paginas.length; i++) {
            gestorBuffer.ponerPaginaEnBuffer(paginas[i]);
            
        }
        System.out.println("contenido del gestor despues de haber puesto bloques");
        System.out.println(gestorBuffer);
        
        System.out.println("Poner una pagina en el buffer: ");
        Pagina paginaN = new Pagina(10, "p10");
        Pagina paginaE = gestorBuffer.ponerPaginaEnBuffer(paginaN);
        System.out.println(paginaE);
        System.out.println(gestorBuffer);
        
        System.out.println("Recuperar la pagina del buffer");
        Pagina pagina1 = gestorBuffer.recuperarPaginaDelBuffer(7);
        System.out.println(pagina1);
        System.out.println(gestorBuffer);
        
        System.out.println("recuperar otra pagina del buffer");
        Pagina pagina2 = gestorBuffer.recuperarPaginaDelBuffer(3);
        System.out.println(pagina2);
        System.out.println(gestorBuffer);
        
    }
}
